package com.sec.etech.bpm.cust.controller;

import cn.hutool.core.bean.BeanUtil;
import com.alibaba.fastjson.JSONObject;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.sec.etech.bpm.cust.dto.EtechBpmTask;
import com.sec.etech.bpm.cust.mapper.EtechTaskOpinionExtMapper;
import com.sec.etech.bpm.cust.mapper.TaskOpinionCommunicateMapper;
import com.sec.etech.bpm.cust.model.EtechTaskOpinionExt;
import com.sec.etech.bpm.cust.model.TaskOpinionCommunicate;
import io.swagger.annotations.*;
import org.activiti.bpmn.model.BpmnModel;
import org.activiti.bpmn.model.GraphicInfo;
import org.activiti.engine.RepositoryService;
import org.openbpm.base.api.aop.annotion.CatchErr;
import org.openbpm.base.api.response.impl.ResultMsg;
import org.openbpm.base.core.util.StringUtil;
import org.openbpm.base.rest.util.RequestUtil;
import org.openbpm.bpm.api.engine.data.BpmFlowDataAccessor;
import org.openbpm.bpm.api.engine.data.result.FlowData;
import org.openbpm.bpm.core.manager.BpmDefinitionManager;
import org.openbpm.bpm.core.manager.BpmInstanceManager;
import org.openbpm.bpm.core.manager.BpmTaskOpinionManager;
import org.openbpm.bpm.core.manager.BpmTaskStackManager;
import org.openbpm.bpm.core.model.BpmDefinition;
import org.openbpm.bpm.core.model.BpmInstance;
import org.openbpm.bpm.core.model.BpmTaskOpinion;
import org.openbpm.bpm.core.model.BpmTaskStack;
import org.openbpm.bpm.rest.controller.BpmInstanceController;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;

import javax.annotation.Resource;
import javax.servlet.http.HttpServletRequest;
import java.util.*;

@RestController
@RequestMapping({"/etech/instance"})
@Api(description = "流程实例服务接口")
public class EtechInstanceController
        extends BpmInstanceController
{

    @Resource
    BpmDefinitionManager bpmDefinitionMananger;

    @Autowired
    RepositoryService repositoryService;

    @Resource
    BpmInstanceManager bpmInstanceManager;

    @Resource
    BpmTaskOpinionManager bpmTaskOpinionManager;

    @Resource
    EtechTaskOpinionExtMapper taskOpinionExtMapper;

    @Autowired
    BpmTaskStackManager bpmTaskStackManager;

    @Resource
    BpmFlowDataAccessor bpmFlowDataAccessor;
    @Resource
    TaskOpinionCommunicateMapper taskOpinionCommunicateMapper;

    @RequestMapping(
            value = {"getOpinionEx"},
            method = {RequestMethod.GET, RequestMethod.POST}
    )
    @CatchErr
    @ApiOperation(
            value = "获取流程意见",
            notes = "通过流程实例ID/任务ID，获取该流程实例下所有的审批意见，并按处理时间排序"
    )
    public ResultMsg<List<EtechTaskOpinionExt>> getOpinionEx(@RequestParam @ApiParam("流程实例ID") String instId, @RequestParam(required = false) @ApiParam("任务ID") String taskId) throws Exception {
        String trace = null;
        if (StringUtil.isNotEmpty(taskId)) {
            BpmTaskOpinion opinion = this.bpmTaskOpinionManager.getByTaskId(taskId);
            if (StringUtil.isNotEmpty(opinion.getTrace())) {
                trace = opinion.getTrace();
            }
        }


        List<EtechTaskOpinionExt> taskOpinionList = taskOpinionExtMapper.selectList(new LambdaQueryWrapper<EtechTaskOpinionExt>()
                .eq(EtechTaskOpinionExt::getInstId, instId)
                .orderByAsc(EtechTaskOpinionExt::getCreateTime)
        );


        List<TaskOpinionCommunicate> taskOpinionCommunicateList = taskOpinionCommunicateMapper.getTaskOpinionCommunicate(instId);

        HashMap<String, List<EtechTaskOpinionExt>> opinionCommunicateMap = new HashMap<>();
        for (TaskOpinionCommunicate item : taskOpinionCommunicateList) {
            String key = item.getParentTaskId();

            if (opinionCommunicateMap.containsKey(key)) {
                opinionCommunicateMap.get(key).add(BeanUtil.copyProperties(item, EtechTaskOpinionExt.class));

            } else {
                ArrayList<EtechTaskOpinionExt> list = new ArrayList<EtechTaskOpinionExt>();
                list.add(BeanUtil.copyProperties(item, EtechTaskOpinionExt.class));
                opinionCommunicateMap.put(key, list);

            }

        }

        for (int i = taskOpinionList.size() - 1; i > -1; i--) {
            EtechTaskOpinionExt taskOpinion = taskOpinionList.get(i);
            String taskIdInOpinion = taskOpinion.getTaskId();

            if (opinionCommunicateMap.containsKey(taskIdInOpinion)) {
                taskOpinionList.addAll(i + 1, opinionCommunicateMap.get(taskIdInOpinion));
            }

        }


        //List<BpmTaskOpinion> taskOpinionList = this.bpmTaskOpinionManager.getByInst(instId, (String)null, (String)null, trace);
        return this.getSuccessResult(taskOpinionList, "获取流程意见成功");
    }


    @RequestMapping(
            value = {"getFlowImageInfoEx"},
            method = {RequestMethod.POST}
    )
    @CatchErr
    @ApiOperation(
            value = "获取流程图相关信息",
            notes = "获取流程图相关信息"
    )
    public ResultMsg<JSONObject> getFlowImageInfoEx(@RequestParam(required = false) @ApiParam("流程实例ID") String instanceId, @RequestParam(required = false) @ApiParam("流程定义ID，流程未启动时使用") String defId, @RequestParam(required = false) @ApiParam("任务id") String taskId) {
        JSONObject data = new JSONObject(true);
        String actDefId;
        if (StringUtil.isNotEmpty(instanceId)) {
            BpmInstance inst = (BpmInstance)this.bpmInstanceManager.get(instanceId);
            actDefId = inst.getActDefId();
            String trace = null;
            if (StringUtil.isNotEmpty(taskId)) {
                BpmTaskOpinion bto = this.bpmTaskOpinionManager.getByTaskId(taskId);
                trace = bto.getTrace();
            }
            // 定制 opinionMap
            Map<String, List<BpmTaskOpinion>> opinionMap = new LinkedHashMap();
            List<EtechTaskOpinionExt> ops = taskOpinionExtMapper.selectList(new LambdaQueryWrapper<EtechTaskOpinionExt>().eq(EtechTaskOpinionExt::getInstId, instanceId));
            //List<BpmTaskOpinion> ops = this.bpmTaskOpinionManager.getByInst(instanceId, (String)null, (String)null, trace);
            ops.forEach((op) -> {
                String key = op.getTaskKey();// .replace(".","_");
                List<BpmTaskOpinion> opinions = (List)opinionMap.computeIfAbsent(key, (k) -> {
                    return new ArrayList();
                });
                opinions.add(op);
            });
            data.put("opinionMap", opinionMap);
            List<BpmTaskStack> stacks = this.bpmTaskStackManager.getByInstIdAndTrace(instanceId, trace);
            data.put("stacks", stacks);
        } else {
            BpmDefinition def = (BpmDefinition)this.bpmDefinitionMananger.get(defId);
            actDefId = def.getActDefId();
        }

        BpmnModel bpmnModel = this.repositoryService.getBpmnModel(actDefId);
        Map<String, GraphicInfo> locationMap = bpmnModel.getLocationMap();
        JSONObject jsonLocationMap = new JSONObject(true);
        jsonLocationMap.putAll(locationMap);
        data.put("nodeMap", jsonLocationMap);
        data.put("nodeIds", jsonLocationMap.keySet());
        //data.put("nodeMap", locationMap);
        return this.getSuccessResult(data);
    }


    @RequestMapping(
            value = {"getInstanceData2"},
            method = {RequestMethod.POST, RequestMethod.GET}
    )
    @CatchErr
    @ApiOperation(
            value = "流程实例数据",
            notes = "获取流程实例相关数据，包含实例信息，业务数据，表单权限、表单数据、表单内容等"
    )
    @ApiImplicitParams({@ApiImplicitParam(
            paramType = "form",
            dataType = "String",
            name = "instanceId",
            value = "流程实例ID"
    ), @ApiImplicitParam(
            paramType = "form",
            dataType = "String",
            name = "readonly",
            value = "是否只读实例",
            defaultValue = "false"
    ), @ApiImplicitParam(
            paramType = "form",
            dataType = "String",
            name = "defId",
            value = "流程定义ID，启动时使用"
    ), @ApiImplicitParam(
            paramType = "form",
            dataType = "String",
            name = "flowKey",
            value = "流程定义Key，启动时使用,与DefId二选一"
    ), @ApiImplicitParam(
            paramType = "form",
            dataType = "String",
            name = "formType",
            value = "表单类型",
            defaultValue = "pc"
    )})
    public ResultMsg getInstanceData2(HttpServletRequest request) throws Exception {
        ResultMsg resultMsg = getInstanceData(request);
        String nodeId = RequestUtil.getString(request, "nodeId");
        String instanceId = request.getParameter("instanceId");
        if(resultMsg.getIsOk() && StringUtil.isNotEmpty(nodeId)){
            FlowData flowData = (FlowData)resultMsg.getData();
            JSONObject jsonData = JSONObject.parseObject(JSONObject.toJSONString(flowData));
            if(!jsonData.containsKey("task")){
                EtechBpmTask task = new EtechBpmTask();
                task.setNodeId(nodeId);
                task.setInstId(instanceId);
                jsonData.put("task", task);
            }
            resultMsg.setData(jsonData);
        }
        return resultMsg;
    }
}
